﻿#include "AreaIdentify.h"
#include "public.h"
#include "easylogging++.h"
#include "ui_mainwindow.h"
#include "mainwindow.h"

AreaIdentify::AreaIdentify(MainWindow& mw, std::shared_ptr<SerialPort> sp) : mainWindow(mw), serialPort(sp) {
	this->queryAreaResultTimer = new QTimer();
	connect(this->queryAreaResultTimer, SIGNAL(timeout()), this, SLOT(sendQueryAreaResultCycle()));
}

void AreaIdentify::startQueryAreaResultTimer(uint32_t ms) {
	if (!isStartedQueryAreaResultTimer) {
		this->queryAreaResultTimer->start(ms);
		isStartedQueryAreaResultTimer = true;
	}
}

void AreaIdentify::sendQueryTerminalNo() {
	auto msg_data = this->queryTerminalNo;
	QByteArray msg = vectorToByteArray(msg_data);
	if (!this->serialPort->cacheWaitConfirmMsg(SerialPort::queryTerminalNoReq, msg)) {
		LOG(ERROR) << "Message has not been confirmed, cmd:" << convertToString(SerialPort::queryTerminalNoReq).toStdString() << ", msg:" << convertToString(msg).toStdString();
		return;
	}
	this->serialPort->sendMsg(msg);
}

void AreaIdentify::sendStartAreaIdentify() {
	auto msg_data = this->startAreaIdentify;
	QByteArray msg = vectorToByteArray(msg_data);
	if (!this->serialPort->cacheWaitConfirmMsg(SerialPort::startAreaIdentifyReq, msg)) {
		LOG(ERROR) << "Message has not been confirmed, cmd:" << convertToString(SerialPort::startAreaIdentifyReq).toStdString() << ", msg:" << convertToString(msg).toStdString();
		return;
	}
	this->serialPort->sendMsg(msg);
}

void AreaIdentify::sendQueryTableFileAreaResult() {
	// 发送查询表档案的台区识别结果
	std::vector<int> content = { hasSearchedTableFileAreaCnt & 0xFF, (hasSearchedTableFileAreaCnt >> 16) & 0xFF, 0x10 };
	this->queryTableFileAreaResult = constructMsgData({ 0x0e, 0x03, 0x03, 0xe8 }, 0x03, content);
	auto msg_data = this->queryTableFileAreaResult;
	QByteArray msg = vectorToByteArray(msg_data);
	this->serialPort->sendMsg(msg);
}

void AreaIdentify::sendQueryRedundantAreaResult() {
	// 查询多余节点的台区识别结果
	std::vector<int> content = { hasSearchedRedundantAreaCnt & 0xFF, (hasSearchedRedundantAreaCnt >> 16) & 0xFF, 0x10 };
	this->queryRedundantAreaResult = constructMsgData({ 0x0f, 0x03, 0x03, 0xe8 }, 0x03, content);
	auto msg_data = this->queryRedundantAreaResult;
	QByteArray msg = vectorToByteArray(msg_data);
	if (!this->serialPort->cacheWaitConfirmMsg(SerialPort::queryRedundantAreaResultReq, msg)) {
		LOG(ERROR) << "Message has not been confirmed, cmd:" << convertToString(SerialPort::queryRedundantAreaResultReq).toStdString() << ", msg:" << convertToString(msg).toStdString();
		return;
	}
	this->serialPort->sendMsg(msg);
}

void AreaIdentify::handleStartAreaIdentifyRsp(const QByteArray& relayMessage) {
	this->serialPort->confirmWaitConfirmMsg(SerialPort::startAreaIdentifyReq);
	// 发送查询台区识别结果
	sendQueryTableFileAreaResult();
	sendQueryRedundantAreaResult();
	// 启动定时台区结果查询
	// startQueryAreaResultTimer(60000 * 2);
}

void AreaIdentify::handleTableFileAreaResult(const QByteArray& relayMessage) {
	uint16_t totalCnt = uint8_t(relayMessage[11]) << 8 | uint8_t(relayMessage[10]);// 总数量
	uint16_t cnt = relayMessage[12]; // 本次应答的节点总数量m
	hasSearchedTableFileAreaCnt += cnt;
	LOG(INFO) << "totalCnt:" << totalCnt << ", cnt:" << cnt;
	for (int i = 0; i < cnt; ++i) {
		std::vector<int> nodeAddr;
		nodeAddr.push_back(relayMessage[13 + i * 7 + 5]);
		nodeAddr.push_back(relayMessage[13 + i * 7 + 4]);
		nodeAddr.push_back(relayMessage[13 + i * 7 + 3]);
		nodeAddr.push_back(relayMessage[13 + i * 7 + 2]);
		nodeAddr.push_back(relayMessage[13 + i * 7 + 1]);
		nodeAddr.push_back(relayMessage[13 + i * 7 + 0]);

		auto nodeAddrStr = convertToStringToShow(vectorToByteArray(nodeAddr));
		int result = relayMessage[13 + i * 7 + 6];
		QString nodeStatus;
		QString terminalNo = "";
		if (result == 0) {
			nodeStatus = "属于";
			terminalNo = this->termialNo;
		}
		else if (result == 1) {
			nodeStatus = "不属于";
			continue;
		}
		else if (result == 2) {
			nodeStatus = "无法通信";
		}
		else if (result == 3) {
			nodeStatus = "待识别";
		}
		else if (result == 4) {
			nodeStatus = "不支持";
		}
		else {
			continue;
		}

		mainWindow.updateAreaViewModel(nodeAddrStr, nodeStatus, terminalNo);
	}
	if (cnt == 0x10) {
		// 发送查询从节点信息
		sendQueryTableFileAreaResult();
	}
	else {
		// 为下次搜索准备
		hasSearchedTableFileAreaCnt = 0;
	}
}

void AreaIdentify::handleRedundantAreaResult(const QByteArray& relayMessage) {
	uint16_t totalCnt = uint8_t(relayMessage[11]) << 8 | uint8_t(relayMessage[10]);// 总数量
	uint16_t cnt = relayMessage[12]; // 本次应答的节点总数量m
	hasSearchedRedundantAreaCnt += cnt;
	LOG(INFO) << "totalCnt:" << totalCnt << ", cnt:" << cnt;
	for (int i = 0; i < cnt; ++i) {
		std::vector<int> nodeAddr;
		nodeAddr.push_back(relayMessage[13 + i * 14 + 5]);
		nodeAddr.push_back(relayMessage[13 + i * 14 + 4]);
		nodeAddr.push_back(relayMessage[13 + i * 14 + 3]);
		nodeAddr.push_back(relayMessage[13 + i * 14 + 2]);
		nodeAddr.push_back(relayMessage[13 + i * 14 + 1]);
		nodeAddr.push_back(relayMessage[13 + i * 14 + 0]);
		auto nodeAddrStr = convertToStringToShow(vectorToByteArray(nodeAddr));

		std::vector<int> terminalNo;
		terminalNo.push_back(relayMessage[13 + i * 14 + 11]);
		terminalNo.push_back(relayMessage[13 + i * 14 + 10]);
		terminalNo.push_back(relayMessage[13 + i * 14 + 9]);
		terminalNo.push_back(relayMessage[13 + i * 14 + 8]);
		terminalNo.push_back(relayMessage[13 + i * 14 + 7]);
		terminalNo.push_back(relayMessage[13 + i * 14 + 6]);
		auto terminalNoStr = convertToStringToShow(vectorToByteArray(terminalNo));

		QString nodeStatus = "不属于";
		mainWindow.updateAreaViewModel(nodeAddrStr, nodeStatus, terminalNoStr);
	}
	if (cnt == 0x10) {
		// 发送查询从节点信息
		sendQueryRedundantAreaResult();
	}
	else {
		// 为下次搜索准备
		hasSearchedRedundantAreaCnt = 0;
	}
}

void AreaIdentify::handleQueryTermialNoResult(const QByteArray& relayMessage) {
	std::vector<int> terminalNo;
	terminalNo.push_back(relayMessage[15]);
	terminalNo.push_back(relayMessage[14]);
	terminalNo.push_back(relayMessage[13]);
	terminalNo.push_back(relayMessage[12]);
	terminalNo.push_back(relayMessage[11]);
	terminalNo.push_back(relayMessage[10]);
	auto terminalNoStr = convertToStringToShow(vectorToByteArray(terminalNo));
	mainWindow.getUi()->terminalNoValueLabel->setText(terminalNoStr);

	mainWindow.getUi()->startAreaIdentifyPushButton->setEnabled(true);
	mainWindow.getUi()->stopAreaIdentifyPushButton->setEnabled(true);
	mainWindow.getUi()->getAreaIdentifyResultPushButton->setEnabled(true);
	mainWindow.getUi()->exportAreaIdentifyResultPushButton->setEnabled(true);
	mainWindow.getUi()->exportPhaseIdentifyResultPushButton->setEnabled(true);
	mainWindow.getUi()->startPhaseIdentifyPushButton->setEnabled(true);
	mainWindow.getUi()->startSearchTablePushButton->setEnabled(true);
	mainWindow.getUi()->stopSearchTablePushButton->setEnabled(true);
	mainWindow.getUi()->getSearchTableResultPushButton->setEnabled(true);
	mainWindow.getUi()->exportSearchTableResultPushButton->setEnabled(true);
	this->serialPort->confirmWaitConfirmMsg(SerialPort::queryTerminalNoReq);

	this->termialNo = terminalNoStr;
}

// 周期查询台区识别结果
void AreaIdentify::sendQueryAreaResultCycle() {
	// sendQueryTableFileAreaResult();
}